package lz.controls.core
{
	import com.common.utils.Reflection;
	import com.greensock.TweenLite;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.InteractiveObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.system.IME;
	import flash.system.IMEConversionMode;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.utils.Dictionary;
	import flash.utils.getQualifiedClassName;
	
	import lz.controls.events.ComponentEvent;
	import lz.controls.managers.FocusManager;
	import lz.controls.managers.IFocusManager;
	import lz.controls.managers.IFocusManagerComponent;
	import lz.controls.managers.StyleManager;
	import lz.controls.managers.TipsManager;

	//--------------------------------------
	//  Class description
	//--------------------------------------	
	/**
	 * IComponent 类是所有可视组件（交互式和非交互式）的基类。
	 * 交互式组件被定义为接收用户输入（例如键盘或鼠标活动）的组件。
	 * 非交互式组件用于显示数据；它们对用户交互不做响应。
	 * ProgressBar 和 UILoader 组件是非交互式组件的示例。
	 * Tab 和箭头键可以用来将焦点移到交互式组件上以及将焦点从交互式组件上移开；
	 * 交互式组件可以接受低级别事件，例如鼠标和键盘设备的输入。
	 *  也可以禁用交互式组件，以便它无法接收鼠标和键盘输入。
	 */
	public class UIComponent extends Sprite
	{
		/**
		 * 皮肤
		 * 某些组件利用flash cs 制作成MovieClip；
		 */		
		public var _symbolSkin:MovieClip;
		/**
		 * 版本
		 */
		public const version:String="4.0.0.1";
		/**
		 * Indicates whether the current execution stack is within a call later phase.
		 * @default false
		 */
		public static var inCallLaterPhase:Boolean=false;
		/**
		 * Used when components are nested, and we want the parent component to
		 * handle draw focus, not the child.
		 * @default null
		 */
		public var focusTarget:IFocusManagerComponent;
		/**
		 * 是否可预览
		 */
		protected var isLivePreview:Boolean=false;
		/**
		 * 临时文本对象
		 */
		private var tempText:TextField;
		/**
		 *样式实例
		 */
		protected var instanceStyles:Object;
		/**
		 * @private (protected)
		 */
		protected var sharedStyles:Object; // Holds a reference to the class-level styles.
		/**
		 * @private (protected)
		 */
		protected var callLaterMethods:Dictionary;
		/**
		 * @private (protected)
		 */
		protected var invalidateFlag:Boolean=false;
		/**
		 * @private (protected)
		 */
		protected var _enabled:Boolean=true;
		/**
		 * @private (protected)
		 */
		protected var invalidHash:Object;
		/**
		 * @private (protected)
		 */
		protected var uiFocusRect:DisplayObject;
		/**
		 * @private (protected)
		 */
		protected var isFocused:Boolean=false
		/**
		 * @private
		 */
		private var _focusEnabled:Boolean=true;
		/**
		 * @private
		 */
		private var _mouseFocusEnabled:Boolean=true;
		/**
		 * @private (protected)
		 */
		protected var _width:Number;
		/**
		 * @private (protected)
		 */
		protected var _height:Number;
		/**
		 * @private (protected)
		 */
		protected var _x:Number;
		/**
		 * @private (protected)
		 */
		protected var _y:Number;
		/**
		 * @private (protected)
		 */
		protected var startWidth:Number;
		/**
		 * @private (protected)
		 */
		protected var startHeight:Number;
		/**
		 * @private (protected)
		 */
		protected var _imeMode:String=null;
		/**
		 * @private (protected)
		 */
		protected var _oldIMEMode:String=null;
		/**
		 * @private (protected)
		 */
		protected var errorCaught:Boolean=false;
		/**
		 * @private (protected)
		 */
		protected var _inspector:Boolean=false;
		/**
		 * tips 显示内容
		 */		
		private var _toolTip :*;
		/**
		 * tips对象名描述
		 */		
		public var tollTipClassRef :String = "ToolTip";
		/**
		 * 默认样式
		 */
		private static var defaultStyles:Object={focusRectSkin: "focusRectSkin", focusRectPadding: 2, textFormat: new TextFormat("_sans", 11, 0x000000, false, false, false, "", "", TextFormatAlign.LEFT, 0, 0, 0, 0), disabledTextFormat: new TextFormat("_sans", 11, 0x999999, false, false, false, "", "", TextFormatAlign.LEFT, 0, 0, 0, 0), defaultTextFormat: new TextFormat("_sans", 11, 0x000000, false, false, false, "", "", TextFormatAlign.LEFT, 0, 0, 0, 0), defaultDisabledTextFormat: new TextFormat("_sans", 11, 0x999999, false, false, false, "", "", TextFormatAlign.LEFT, 0, 0, 0, 0)}
		/**
		 * @private
		 */
		private static var focusManagers:Dictionary=new Dictionary(true);
		/**
		 * @private
		 */
		private static var focusManagerUsers:Dictionary=new Dictionary(true);
		/**
		 * 检索当前组件的默认样式映射。 样式映射包含适合组件的类型，具体取决于组件使用的样式。
		 * 例如，disabledTextFormat 样式包含 null 值或 TextFormat 对象。
		 * 可以使用这些样式并对当前组件调用 setStyle()。
		 * 下面的代码覆盖指定组件上默认的 disabledTextFormat 样式：
		 * componentInstance.setStyle("disabledTextFormat", new TextFormat());
		 * 返回
		 * Object — 默认样式对象。
		 */
		public static function getStyleDefinition():Object
		{
			return defaultStyles;
		}

		/**
		 *将多个类的样式合并到一个对象中。 如果在多个对象中定义了某种样式，则使用找到的第一个对象的样式。
		 * 参数
		 * ... list — 包含要合并的默认样式的逗号分隔对象列表。
		 * 返回
		 * Object — 包含合并样式的默认样式对象。
		 */
		public static function mergeStyles(... list:Array):Object
		{
			var styles:Object={};
			var l:uint=list.length;
			for (var i:uint=0; i < l; i++)
			{
				var styleList:Object=list[i];
				for (var n:String in styleList)
				{
					if (styles[n] != null)
					{
						continue;
					}
					styles[n]=list[i][n];
				}
			}
			return styles;
		}


		/**
		 *  @private
		 *  @internal (Placeholder for mixin by UIComponentAccImpl)
		 *
		 *  Creates the Accessibility class to be associated with the current component.
		 */
		public static var createAccessibilityImplementation:Function;


		/**
		 * 创建新的 UIComponent 组件实例。
		 */
		public function UIComponent()
		{
			super();

			instanceStyles={};
			sharedStyles={};
			invalidHash={};

			callLaterMethods=new Dictionary();

			StyleManager.registerInstance(this);

			configUI();
			invalidate(InvalidationType.ALL);
			// We are tab enabled by default if IFocusManagerComponent
			tabEnabled=(this is IFocusManagerComponent);
			// We do our own focus drawing.
			focusRect=false;

			// Register for focus and keyboard events.
			if (tabEnabled)
			{
				addEventListener(FocusEvent.FOCUS_IN, focusInHandler);
				addEventListener(FocusEvent.FOCUS_OUT, focusOutHandler);
				addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
				addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			}

			initializeFocusManager()
			addEventListener(Event.ENTER_FRAME, hookAccessibility, false, 0, true);
		}


		/**
		 * @private (internal)
		 */
		public function get componentInspectorSetting():Boolean
		{
			return _inspector;
		}

		public function set componentInspectorSetting(value:Boolean):void
		{
			_inspector=value;
			if (_inspector)
			{
				beforeComponentParameters();
			}
			else
			{
				afterComponentParameters();
			}
		}

		// For easy overriding...
		/**
		 */
		protected function beforeComponentParameters():void
		{
		}
		protected function afterComponentParameters():void
		{
		}
		/**
		 * 获取或设置一个值，该值指示组件是否可以接受用户交互。 true 值指示组件可以接受用户交互；false 值指示组件无法接受用户交互。
		 * 如果将 enabled 属性设置为 false，则容器的颜色将变暗，并且禁止用户输入（Label 和 ProgressBar 组件除外）。
		 * 默认值为 true。
		 */
		public function get enabled():Boolean
		{
			return _enabled;
		}
		public function set enabled(value:Boolean):void
		{
			if (value == _enabled)
			{
				return;
			}
			_enabled=value;
			invalidate(InvalidationType.STATE);
		}

		/**
		 * 获取或设置组件的宽度（以像素为单位）。
		 * 设置此属性将导致 resize 事件被调度。请参阅“resize 事件”，了解有关何时调度该事件的详细信息。
		 * 如果组件的 scaleX 属性不是 1.0，则从其内部坐标获得的组件宽度将与父坐标的宽度值不匹配。 
		 * 例如，一个宽度为 100 像素并且 scaleX 为 2 的组件在父项中具有 100 像素的值，但内部却存储一个指示其为 50 像素宽的值。
		 */
		override public function get width():Number
		{
			return _width;
		}
		override public function set width(value:Number):void
		{
			if (_width == value)
			{
				return;
			}
			setSize(value, height);
		}

		/**
		 * 获取或设置组件的高度，以像素为单位。
		 * 设置此属性将导致 resize 事件被调度。请参阅“resize 事件”，了解有关何时调度该事件的详细信息。
		 * 如果组件的 scaleY 属性不是 1.0，则从其内部坐标获得的组件高度将与父坐标的高度值不匹配。 
		 * 例如，一个宽度为 100 像素并且 scaleY 为 2 的组件在父项中具有 100 像素的值，但内部却存储一个指示其为 50 像素高的值。
		 */
		override public function get height():Number
		{
			return _height;
		}
		override public function set height(value:Number):void
		{
			if (_height == value)
			{
				return;
			}
			setSize(width, value);
		}
		/**
		 * 对此组件实例设置样式属性。 该样式可能会覆盖以全局方式设置的样式。
		 * 调用该方法会导致性能降低。 仅在必要时才使用它。
		 * 参数
		 * style:String — 样式属性的名称。
		 * value:Object — 样式的值。
		 */
		public function setStyle(style:String, value:Object):void
		{
			//Use strict equality so we can set a style to null ... so if the instanceStyles[style] == undefined, null is still set.
			//We also need to work around the specific use case of TextFormats
			if (instanceStyles[style] === value && !(value is TextFormat))
			{
				return;
			}
			instanceStyles[style]=value;
			invalidate(InvalidationType.STYLES);
		}
		/**
		 * 检索组件的样式查找链中设置的样式属性。
		 * 根据方法检索的样式属性，该方法返回的类型会有所不同。 可能类型的范围包括 Boolean、String、Number、int、用于 RGB 颜色的 uint、用于外观的 Class 或任何对象类型。
		 * 如果调用该方法来检索特定样式属性，其类型将为已知类型，您可以将其存储在相同类型的变量中。 
		 * 不需要进行类型转换。 
		 * 一条类似如下所示的简单赋值语句即可起作用：
		 * var backgroundColor:uint = getStyle("backgroundColor");
		 * 如果样式查找链中未设置样式属性，则该方法返回 undefined 值。
		 * 注意，undefined 是一个特殊的值，它不同于 false、""、NaN、0 或 null。
		 * 如果没有有效的样式值，则总是 undefined。
		 * 可以使用静态方法 StyleManager.isValidStyleValue() 来测试是否设置了值。
		 * 参数
		 * style:String — 样式属性的名称。
		 * 返回
		 * Object — 样式值。
		 */
		public function getStyle(style:String):Object
		{
			return instanceStyles[style]
		}
		/**
		 * 删除此组件实例的样式属性。
		 * 这并不一定会导致 getStyle() 方法返回 undefined 值。
		 * 参数
		 * style:String — 样式属性的名称。
		 */
		public function clearStyle(style:String):void
		{
			setStyle(style, null);
		}
		/**
		 * 将组件移动到其父项内的指定位置。 这与通过设置其 x 和 y 属性更改组件位置的效果相同。 
		 * 调用该方法将触发 ComponentEvent.MOVE 事件被调度。
		 * 若要覆盖自定义组件中的 updateDisplayList() 方法，请使用 move() 方法，而不是设置 x 和 y 属性。 
		 * 这是因为，对 move() 方法的调用会导致 move 事件对象在移动操作完成以后立即被调度。 
		 * 相比之下，通过设置 x 和 y 属性更改组件位置时，事件对象会在下一次刷新屏幕时被调度。
		 * 参数
		 * x:Number — 指定组件在其父项内位置的 x 坐标值（以像素为单位）。从左边计算该值。
		 * y:Number — 指定组件在其父项内位置的 y 坐标值（以像素为单位）。从顶部计算该值。
		 */
		public function move(x:Number, y:Number):void
		{
			_x=x;
			_y=y;
			super.x=Math.round(x);
			super.y=Math.round(y);
			dispatchEvent(new ComponentEvent(ComponentEvent.MOVE));
		}

		/**
		 * 获取或设置 x 坐标，该坐标表示组件在其父容器内沿 x 轴的位置。 
		 * 以像素为单位描述该值并且从左边计算该值。
		 * 设置此属性将导致 ComponentEvent.MOVE 事件被调度。
		 * 默认值为 0。
		 */
		override public function get x():Number
		{
			return (isNaN(_x)) ? super.x : _x;
		}
		override public function set x(value:Number):void
		{
			move(value, _y);
		}
		/**
		 * 获取或设置 y 坐标，该坐标表示组件在其父容器内沿 y 轴的位置。 
		 * 以像素为单位描述该值并且从顶部计算该值。
		 * 设置此属性将导致 move 事件被调度。
		 */
		override public function get y():Number
		{
			return (isNaN(_y)) ? super.y : _y;
		}
		override public function set y(value:Number):void
		{
			move(_x, value);
		}
		/**
		 *将组件的当前宽度与缩放系数相乘。
		 */
		override public function get scaleX():Number
		{
			return width / startWidth;
		}
		override public function set scaleX(value:Number):void
		{
			setSize(startWidth * value, height);
		}
		/**
		 * 将组件的当前高度与缩放系数相乘。
		 */
		override public function get scaleY():Number
		{
			return height / startHeight;
		}
		override public function set scaleY(value:Number):void
		{
			setSize(width, startHeight * value);
		}
		/**
		 * @private (protected)
		 */
		protected function getScaleY():Number
		{
			return super.scaleY;
		}
		/**
		 * @private (protected)
		 */
		protected function setScaleY(value:Number):void
		{
			super.scaleY=value;
		}
		/**
		 * @private (protected)
		 */
		protected function getScaleX():Number
		{
			return super.scaleX;
		}
		/**
		 * @private (setter)
		 */
		protected function setScaleX(value:Number):void
		{
			super.scaleX=value;
		}
		/**
		 * 获取或设置一个值，该值指示当前组件实例是否可见。 
		 * true 值指示当前组件可见；false 值指示其不可见。
		 * 该属性设置为 true 时，对象将调度 show 事件。该属性设置为 false 时，对象将调度 hide 事件。
		 * 无论在哪种情况下，对象的子项都不会生成 show 或 hide 事件，除非明确地针对该对象编写一个实现来执行此操作。
		 * 默认值为 true。
		 */
		override public function get visible():Boolean
		{
			return super.visible;
		}
		override public function set visible(value:Boolean):void
		{
			if (super.visible == value)
			{
				return;
			}
			super.visible=value;
			var t:String=(value) ? ComponentEvent.SHOW : ComponentEvent.HIDE;
			dispatchEvent(new ComponentEvent(t, true));
		}
		/**
		 * 验证并更新此对象的属性和布局，如果需要的话重绘对象。
		 * 通常只有当脚本执行完毕后，才会处理需要大量计算的属性。 
		 * 这是因为，设置一个属性可能需要处理其他属性。 
		 * 例如，设置 width 属性可能需要同时计算对象子项或父项的宽度。 
		 * 而且，如果脚本多次重新计算对象的宽度，则这些相互依赖的属性可能也需要重新计算。 
		 * 使用该方法可以手动覆盖该行为。
		 */
		public function validateNow():void
		{
			invalidate(InvalidationType.ALL, false);
			draw();
		}
		/**
		 * 在未另外指定的情况下，将属性标记为无效，并在下一帧上重绘组件。
		 * 参数
		 * property:String (default = NaN) — 要使其无效的属性。
		 * callLater:Boolean (default = true) — 一个布尔值，该值指示是否应该在下一帧上重绘组件。默认值为 true。
		 */
		public function invalidate(property:String=InvalidationType.ALL, callLater:Boolean=true):void
		{
			invalidHash[property]=true;
			if (callLater)
			{
				this.callLater(draw);
			}
		}
		/**
		 * @private (internal)
		 */
		public function setSharedStyle(name:String, style:Object):void
		{
			if (sharedStyles[name] === style && !(style is TextFormat))
			{
				return;
			}
			sharedStyles[name]=style;
			if (instanceStyles[name] == null)
			{
				invalidate(InvalidationType.STYLES);
			}
		}
		/**
		 * 获取或设置一个布尔值，该值指示组件是否可以在用户单击它后获得焦点。 true 值指示其可以获得焦点；false 值指示其无法获得焦点。
		 * 如果该属性为 false，焦点会转移到其 mouseFocusEnabled 属性设置为 true 的第一个父项。
		 * 默认值为 true。
		 */
		public function get focusEnabled():Boolean
		{
			return _focusEnabled;
		}
		public function set focusEnabled(b:Boolean):void
		{
			_focusEnabled=b;
		}

		/**
		 * 获取或设置一个值，该值指示组件是否可以在用户单击它后获得焦点。 
		 * true 值指示其可以获得焦点；false 值指示其无法获得焦点。
		 * 如果该属性为 false，焦点会转移到其 mouseFocusEnabled 属性设置为 true 的第一个父项。
		 * 默认值为 true。
		 */
		public function get mouseFocusEnabled():Boolean
		{
			return _mouseFocusEnabled;
		}
		public function set mouseFocusEnabled(b:Boolean):void
		{
			_mouseFocusEnabled=b;
		}
		/**
		 * 获取或设置为此组件及其同级组件控制焦点的 FocusManager。 
		 * 每个弹出组件都保留有自己的焦点循环和 FocusManager 实例。 
		 * 使用该属性可以访问该组件的正确 FocusManager。
		 */
		public function get focusManager():IFocusManager
		{
			var o:DisplayObject=this;
			while (o)
			{
				if (UIComponent.focusManagers[o] != null)
				{
					return IFocusManager(UIComponent.focusManagers[o]);
				}
				o=o.parent;
			}
			return null;
		}
		public function set focusManager(f:IFocusManager):void
		{
			UIComponent.focusManagers[this]=f;
		}
		/**
		 * 在此组件上显示或隐藏焦点指示符。
		 * UIComponent 类通过创建并放置 focusSkin 样式指定的类的实例来实现该方法。
		 * 参数
		 * focused:Boolean — 指示是显示还是隐藏焦点指示符。
		 * 如果该值为 true，则显示焦点指示符；
		 * 如果该值为 false，则隐藏焦点指示符。
		 */
		public function drawFocus(focused:Boolean):void
		{
			isFocused=focused; // We need to set isFocused here since there are drawFocus() calls from FM.

			//Remove uiFocusRect if focus is turned off
			if (uiFocusRect != null && contains(uiFocusRect))
			{
				removeChild(uiFocusRect);
				uiFocusRect=null;
			}
			//Add focusRect to stage, and resize.  If component is focused.
			if (focused)
			{
				uiFocusRect=getDisplayObjectInstance(getStyleValue("focusRectSkin")) as Sprite;
				if (uiFocusRect == null)
				{
					return;
				}
				var focusPadding:Number=Number(getStyleValue("focusRectPadding"));

				uiFocusRect.x=-focusPadding;
				uiFocusRect.y=-focusPadding;
				uiFocusRect.width=width + (focusPadding * 2);
				uiFocusRect.height=height + (focusPadding * 2);

				addChildAt(uiFocusRect, 0);
			}
		}
		/**
		 * 设置此组件的焦点。组件可能接下来将焦点提供给子组件。
		 * 注意：此方法设置焦点时，只有 TextInput 和 TextArea 组件显示焦点指示符。 
		 * 所有组件在用户使用 Tab 切换到它时都显示焦点指示符。
		 */
		public function setFocus():void
		{
			if (stage)
			{
				stage.focus=this;
			}
		}
		/**
		 * 检索当前具有焦点的对象。
		 * 请注意，此方法不一定返回具有焦点的组件。
		 * 它可能返回具有焦点的组件的内部子组件。
		 * 若要获取具有焦点的组件，请使用 focusManager.focus 属性。
		 * 返回
		 * InteractiveObject — 具有焦点的对象；否则，该方法返回 null。
		 */
		public function getFocus():InteractiveObject
		{
			if (stage)
			{
				return stage.focus;
			}
			return null;
		}
		/**
		 */
		protected function setIMEMode(enabled:Boolean):void
		{
			if (_imeMode != null)
			{
				if (enabled)
				{
					IME.enabled=true;
					_oldIMEMode=IME.conversionMode;
					try
					{
						if (!errorCaught && IME.conversionMode != IMEConversionMode.UNKNOWN)
						{
							IME.conversionMode=_imeMode;
						}
						errorCaught=false;
					}
					catch (e:Error)
					{
						errorCaught=true;
						throw new Error("IME mode not supported: " + _imeMode);
					}
				}
				else
				{
					if (IME.conversionMode != IMEConversionMode.UNKNOWN && _oldIMEMode != IMEConversionMode.UNKNOWN)
					{
						IME.conversionMode=_oldIMEMode;
					}
					IME.enabled=false;
				}
			}
		}
		/**
		 * 启动立即绘制操作，但不像 invalidateNow 那样使全部设置失效。
		 */
		public function drawNow():void
		{
			draw();
		}
		/**
		 *配置UI
		 */
		protected function configUI():void
		{
			isLivePreview=checkLivePreview();
			var r:Number=rotation;
			rotation=0;
			var w:Number=super.width;
			var h:Number=super.height;
			super.scaleX=super.scaleY=1;
			setSize(w, h);
			move(super.x, super.y);
			rotation=r;
			startWidth=w;
			startHeight=h;
			if (numChildren > 0)
			{
				//removeChildAt(0);
			}
		}
		/**
		 */
		protected function checkLivePreview():Boolean
		{
			if (parent == null)
			{
				return false;
			}
			var className:String;
			try
			{
				className=getQualifiedClassName(parent);
			}
			catch (e:Error)
			{
			}
			return (className == "fl.livepreview::LivePreviewParent");
		}

		// Included the first property as a proper param to enable *some* type checking, and also because it is a required param.		
		/**
		 * @private (protected)
		 */
		protected function isInvalid(property:String, ... properties:Array):Boolean
		{
			if (invalidHash[property] || invalidHash[InvalidationType.ALL])
			{
				return true;
			}
			while (properties.length > 0)
			{
				if (invalidHash[properties.pop()])
				{
					return true;
				}
			}
			return false
		}
		/**
		 * @private (protected)
		 */
		protected function validate():void
		{
			invalidHash={};
		}
		/**
		 */
		protected function draw():void
		{
			// classes that extend UIComponent should deal with each possible invalidated property
			// common values include all, size, enabled, styles, state
			// draw should call super or validate when finished updating
			if (isInvalid(InvalidationType.SIZE, InvalidationType.STYLES))
			{
				if (isFocused && focusManager.showFocusIndicator)
				{
					drawFocus(true);
				}
			}
			validate();
		}
		/**
		 * 获取对象实例
		 */
		protected function getDisplayObjectInstance(skin:Object):DisplayObject
		{
			//trace(skin);
			if (skin == null || skin == "")
			{
				return null;
			}
			var classDef:Object=null;
			if (skin is Class)
			{
				//trace("skin is Class");
				return (new skin()) as DisplayObject;
			}
			else if (skin is DisplayObject)
			{
				//trace("skin is DisplayObject");
				(skin as DisplayObject).x=0;
				(skin as DisplayObject).y=0;
				return skin as DisplayObject;
			}

			try
			{
				classDef=Reflection.createInstance(skin.toString());
			}
			catch (e:Error)
			{
				try
				{
					classDef=loaderInfo.applicationDomain.getDefinition(skin.toString()) as Object;
				}
				catch (e:Error)
				{
					trace(e);
						// Nothing
				}
			}
			if (classDef is BitmapData)
			{
				return new Bitmap(classDef as BitmapData);
			}
			else if (classDef is DisplayObject)
			{
				return classDef as DisplayObject;
			}
			if (classDef == null)
			{
				return null;
			}
			return (new classDef()) as DisplayObject;
		}
		/**
		 * 获取样式对象
		 */
		protected function getStyleValue(name:String):Object
		{
			return (instanceStyles[name] == null) ? sharedStyles[name] : instanceStyles[name];
		}
		/**
		 * 把样式添加到子组件
		 */
		protected function copyStylesToChild(child:UIComponent, styleMap:Object):void
		{
			if (child == null)
			{
				return;
			}
			for (var n:String in styleMap)
			{
				child.setStyle(n, getStyleValue(styleMap[n]));
			}
		}
		/**
		 *调用函数
		 */
		protected function callLater(fn:Function):void
		{
			if (inCallLaterPhase)
			{
				return;
			}
			callLaterMethods[fn]=true;
			if (stage != null)
			{
				stage.addEventListener(Event.RENDER, callLaterDispatcher, false, 0, true);
				stage.invalidate();
			}
			else
			{
				addEventListener(Event.ADDED_TO_STAGE, callLaterDispatcher, false, 0, true);
			}
		}
		/**
		 */
		private function callLaterDispatcher(event:Event):void
		{
			if (event.type == Event.ADDED_TO_STAGE)
			{
				removeEventListener(Event.ADDED_TO_STAGE, callLaterDispatcher);
				// now we can listen for render event:
				stage.addEventListener(Event.RENDER, callLaterDispatcher, false, 0, true);
				stage.invalidate();

				return;
			}
			else
			{
				event.target.removeEventListener(Event.RENDER, callLaterDispatcher);
				if (stage == null)
				{
					// received render, but the stage is not available, so we will listen for addedToStage again:
					addEventListener(Event.ADDED_TO_STAGE, callLaterDispatcher, false, 0, true);
					return;
				}
			}

			inCallLaterPhase=true;

			var methods:Dictionary=callLaterMethods;
			for (var method:Object in methods)
			{
				method();
				delete(methods[method]);
			}
			inCallLaterPhase=false;
		}
		/**
		 * @private
		 */
		private function initializeFocusManager():void
		{
			// create root FocusManager
			if (stage == null)
			{
				// we don't have stage yet, wait for it
				addEventListener(Event.ADDED_TO_STAGE, addedHandler, false, 0, true);
			}
			else
			{
				// we have stage: if not already created, create FocusManager
				createFocusManager();
				var fm:IFocusManager=focusManager;
				if (fm != null)
				{
					var fmUserDict:Dictionary=focusManagerUsers[fm];
					if (fmUserDict == null)
					{
						fmUserDict=new Dictionary(true);
						focusManagerUsers[fm]=fmUserDict;
					}
					fmUserDict[this]=true;
				}
			}
			addEventListener(Event.REMOVED_FROM_STAGE, removedHandler);
		}
		/**
		 * @private
		 */
		private function addedHandler(evt:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, addedHandler);
			initializeFocusManager();
		}
		/**
		 * @private
		 */
		private function removedHandler(evt:Event):void
		{
			removeEventListener(Event.REMOVED_FROM_STAGE, removedHandler);
			addEventListener(Event.ADDED_TO_STAGE, addedHandler);
			var fm:IFocusManager=focusManager;
			if (fm != null)
			{
				// check to see if any components are registered as users of this IFocusManager
				var fmUserDict:Dictionary=focusManagerUsers[fm];
				if (fmUserDict != null)
				{
					delete fmUserDict[this];
					var dictEmpty:Boolean=true;
					for (var key:* in fmUserDict)
					{
						dictEmpty=false;
						break;
					}
					if (dictEmpty)
					{
						delete focusManagerUsers[fm];
						fmUserDict=null;
					}
				}
				// if there are no users registered, deactivate the IFocusManager and remove it from
				// the focusManagers Dictionary to ensure it can be garbage collected.
				if (fmUserDict == null)
				{
					fm.deactivate();
					for (var key2:* in focusManagers)
					{
						var compFM:IFocusManager=focusManagers[key2];
						if (fm == compFM)
							delete focusManagers[key2];
					}
				}
			}
		}
		/**
		 * @private (protected)
		 */
		protected function createFocusManager():void
		{
			if (focusManagers[stage] == null)
			{
				focusManagers[stage]=new FocusManager(stage);
			}
		}
		/**
		 * @private (protected)
		 */
		protected function isOurFocus(target:DisplayObject):Boolean
		{
			return (target == this);
		}
		/**
		 * @private (protected)
		 */
		protected function focusInHandler(event:FocusEvent):void
		{
			if (isOurFocus(event.target as DisplayObject))
			{
				var fm:IFocusManager=focusManager;
				if (fm && fm.showFocusIndicator)
				{
					drawFocus(true);
					isFocused=true;
				}
			}
		}
		/**
		 * @private (protected)
		 */
		protected function focusOutHandler(event:FocusEvent):void
		{
			if (isOurFocus(event.target as DisplayObject))
			{
				drawFocus(false);
				isFocused=false;
			}
		}
		/**
		 * @private (protected)
		 */
		protected function keyDownHandler(event:KeyboardEvent):void
		{
			// You must override this function if your component accepts focus
		}
		/**
		 * @private (protected)
		 */
		protected function keyUpHandler(event:KeyboardEvent):void
		{
			// You must override this function if your component accepts focus
		}
		/**
		 *  @private (protected)
		 *  Triggers initialization of this component's accessibility code.
		 */
		protected function hookAccessibility(event:Event):void
		{
			removeEventListener(Event.ENTER_FRAME, hookAccessibility);
			initializeAccessibility();
		}
		/**
		 *  @private (protected)
		 *  Initializes this component's accessibility code.
		 */
		protected function initializeAccessibility():void
		{
			if (UIComponent.createAccessibilityImplementation != null)
			{
				UIComponent.createAccessibilityImplementation(this);
			}
		}
		/**
		 *设置大小
		 * @param width
		 * @param height
		 */
		public function setSize(width:Number, height:Number):void
		{
			_width=width;
			_height=height;
			invalidate(InvalidationType.SIZE);
			dispatchEvent(new ComponentEvent(ComponentEvent.RESIZE, false));
		}
		/**
		 *要在 ToolTip 中显示的数据
		 */		
		public function set toolTip(value :*):void
		{
			if(value == null || value == _toolTip)
			{
				return;
			}
			_toolTip = value;
			//添加事件
			addEventListener(MouseEvent.ROLL_OVER,onRollOver);
			addEventListener(MouseEvent.ROLL_OUT,onRollOut);
		}
		public function get toolTip():*
		{
			return _toolTip;
		}
		/**
		 *鼠标移上 
		 * @param e
		 * 
		 */		
		protected function onRollOver(e :MouseEvent):void
		{
			TipsManager.show(tollTipClassRef,_toolTip,10,10);
		}
		/**
		 * 鼠标移出
		 * @param e
		 * 
		 */		
		protected function onRollOut(e :MouseEvent):void
		{
			TipsManager.hide();
		}
		/**
		 *浅入时间 
		 */		
		public var fadeInDuration	:Number = .3;
		/**
		 *淡出时间 
		 */		
		public var fadeOutDuration	:Number = .2;
		/**
		 *浅入 
		 * 
		 */		
		public function fadeIn():void
		{
			if(_symbolSkin == null)
			{
				return;
			}
			_symbolSkin.alpha = 0;
			TweenLite.to(_symbolSkin,fadeInDuration,{alpha:1});
		}
		/**
		 * 淡出
		 */		
		public function fadeOut():void
		{
			if(_symbolSkin == null)
			{
				return;
			}
			TweenLite.to(_symbolSkin,fadeInDuration,{alpha:0,onComplete:fadeOutComplete});
		}
		/**
		 * 淡出 完毕 可以做清理工作
		 */		
		protected function fadeOutComplete():void
		{
			trace("fadeOutComplete");
		}
		/**
		 * 销毁
		 */
		public function destroy():void
		{
			removeEventListener(MouseEvent.ROLL_OVER,onRollOver);
			removeEventListener(MouseEvent.ROLL_OUT,onRollOut);
		}
	}
}
